﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.ComponentModel;
using DevComponents.AdvTree;
using System.Collections;
using System.Collections.Specialized;

namespace PolePosition.v3.Desktop.Grids
{
    public class BindableAdvTree : DevComponents.AdvTree.AdvTree
    {
        private Node m_FirstLevelNode;
        private bool m_ChildNodeDefined = false;
        private CellCollection m_ChildCells = null;
        private ColumnHeaderCollection m_ChildColumns = null;
        private string m_ChildCollectionPropertyName = null;

        public BindableAdvTree()
        {

        }

        [Browsable(false)]
        public System.Windows.Forms.BindingSource DataSource { get; set; }

        public void Bind()
        {
            DateTime startTime = DateTime.Now;
            DateTime stopTime;
            TimeSpan _ts;

            //no data?
            if (DataSource == null)
                return;

            if (m_FirstLevelNode == null)
                m_FirstLevelNode = CopyFirstLevelNode(this.Nodes);

            this.Nodes.Clear();

            if (m_FirstLevelNode == null)
                return;

            PopulateData();

            stopTime = DateTime.Now;
            _ts = stopTime - startTime;
            System.Diagnostics.Debug.WriteLine("Build Tree Duration:" + _ts.Duration().TotalSeconds.ToString());
        }

        private void PopulateData()
        {
            int _Counter = 0;
            string _BindingColumnName;

            CellBindings _CellBindings;
            foreach (object _Entity in DataSource)
            {
                _BindingColumnName = this.Columns[0].ColumnName;
                _CellBindings = new CellBindings(null, _BindingColumnName, _Entity);

                Node _NewNode = new Node
                {
                    Tag = _CellBindings,
                    //TagString = m_FirstLevelNode.TagString,
                    Text = _CellBindings.GetDisplayText()
                };

                for (int _ColumnCellIndex = 1; _ColumnCellIndex < m_FirstLevelNode.Cells.Count; _ColumnCellIndex++)
                {
                    Cell _Cell = m_FirstLevelNode.Cells[_ColumnCellIndex];
                    _BindingColumnName = this.Columns[_ColumnCellIndex].ColumnName;
                    _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _Entity);

                    _NewNode.Cells.Add(
                        new Cell()
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        });
                }

                this.Nodes.Add(_NewNode);

                if (m_ChildNodeDefined)
                {
                    System.Windows.Forms.BindingSource _ChildDataSource;
                    _ChildDataSource = GetChildDataBindingSource(_Entity, m_ChildCollectionPropertyName);

                    //add columns first
                    ColumnHeader _NewHeader;
                    foreach (ColumnHeader _Header in m_ChildColumns)
                    {

                        _NewHeader = new ColumnHeader()
                        {
                            ColumnName = _Header.ColumnName,
                            Text = _Header.Text,
                        };
                        _NewHeader.Width.Absolute = _Header.Width.Absolute;
                        _NewNode.NodesColumns.Add(_NewHeader);
                    }

                    foreach (object _ChildEntity in _ChildDataSource)
                    {
                        _BindingColumnName = _NewNode.NodesColumns[0].ColumnName;
                        _CellBindings = new CellBindings(null, _BindingColumnName, _ChildEntity);

                        Node _ChildNode = new Node
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        };
                        
                        for (int i = 1; i < m_ChildCells.Count; i++)
                        {
                            Cell _Cell = m_ChildCells[i];
                            _BindingColumnName = _NewNode.NodesColumns[i].ColumnName;
                            _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _ChildEntity);

                            _ChildNode.Cells.Add(new Cell()
                            {
                                Tag = _CellBindings,
                                Text = _CellBindings.GetDisplayText()
                            });
                        }

                        _NewNode.Nodes.Add(_ChildNode);
                    }
                }

                _Counter++;
                if (_Counter >= 100)
                    return;
            }
        }

        private System.Windows.Forms.BindingSource GetChildDataBindingSource(object parentData, string childPropertyName)
        {
            if (parentData == null)
                ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("parentData"));

            System.Reflection.PropertyInfo _PropertyInfo;
            _PropertyInfo = parentData.GetType().GetProperty(childPropertyName);

            if (_PropertyInfo == null)
                ProjectCommon2.Helpers.ExceptionHelper.Throw(new Exception(childPropertyName + " property not found in entity."));

            object _Object;
            _Object = _PropertyInfo.GetValue(parentData, null);

            System.Windows.Forms.BindingSource _Binding;
            _Binding = new System.Windows.Forms.BindingSource();
            _Binding.DataSource = _Object;

            return _Binding;
        }

        private Node CopyFirstLevelNode(NodeCollection nodes)
        {
            Node _FirstLevelNode = null;

            foreach (Node _Node in nodes)
            {
                if (_Node.Level == 0)
                {
                    _FirstLevelNode = _Node;
                    break;
                }
            }

            if (_FirstLevelNode == null)
                return null;

            Node _NewNode = _FirstLevelNode.DeepCopy();

            // hosted controls do not copy - so store in the tag
            for (int i = 0; i < _FirstLevelNode.Cells.Count; i++)
            {
                if (_FirstLevelNode.Cells[i].HostedControl != null)
                {
                    _NewNode.Cells[i].Tag = _FirstLevelNode.Cells[i].HostedControl;
                }
            }

            if (_FirstLevelNode.HasColumns)
                m_ChildColumns = _FirstLevelNode.NodesColumns;

            if (_FirstLevelNode.HasChildNodes && !string.IsNullOrEmpty(_FirstLevelNode.TagString))
            {
                m_ChildCollectionPropertyName = _FirstLevelNode.TagString;
                m_ChildCells = _FirstLevelNode.Nodes[0].Cells;

                // hosted controls do not copy - so store in the tag
                for (int i = 0; i < m_ChildCells.Count; i++)
                {
                    if ( _FirstLevelNode.Nodes[0].Cells[i].HostedControl != null)
                    {
                        m_ChildCells[i].Tag = _FirstLevelNode.Nodes[0].Cells[i].HostedControl;
                    }
                }
            }

            if (m_ChildCells != null && m_ChildColumns != null)
                m_ChildNodeDefined = true;

            return _NewNode;
        }

        public object GetSelectedEntity()
        {
            if (this.SelectedNode == null)
                return null;

            return (this.SelectedNode.Tag as CellBindings).BoundEntity;
        }

        private class CellBindings
        {
            private System.Windows.Forms.Control m_HostedControl;
            private string m_BindingColumnName;
            object m_BoundEntity;

            public CellBindings(System.Windows.Forms.Control hostedControl, string bindingColumnName, object boundEntity)
            {
                m_HostedControl = hostedControl;
                m_BindingColumnName = bindingColumnName;
                m_BoundEntity = boundEntity;

            }

            public string FormatString { get; set; }
            public bool ReadOnly { get; set; }
            public object BoundEntity { get { return m_BoundEntity; } }


            public string GetDisplayText()
            {

                string _Text;

                if (m_BoundEntity is DataRowView)
                    _Text = GetValueString((DataRowView)m_BoundEntity, m_BindingColumnName);
                else
                    _Text = GetPropertyValueString(m_BoundEntity, m_BindingColumnName);

                //currently only type of hosted conntrol supported bill be ComboBoxEx
                if (m_HostedControl == null || typeof(DevComponents.DotNetBar.Controls.ComboBoxEx) != m_HostedControl.GetType())
                    return _Text;

                DevComponents.DotNetBar.Controls.ComboBoxEx _Combo;
                _Combo = m_HostedControl as DevComponents.DotNetBar.Controls.ComboBoxEx;

                if (_Combo.DataSource == null)
                    return _Text;

                string _DisplayMember = _Combo.DisplayMember;
                string _ValueMember = _Combo.ValueMember;

                if (string.IsNullOrEmpty(_ValueMember) || string.IsNullOrEmpty(_DisplayMember))
                    return _Text;

                if (_ValueMember == _DisplayMember)
                    return _Text;

                string _Value;
                //translate text based upon values stored in combo datasource (must be a binding source)
                foreach (object item in _Combo.DataSource as System.Windows.Forms.BindingSource)
                {
                    _Value = GetPropertyValueString(item, _ValueMember);

                    if (_Value == _Text)
                    {
                        _Text = GetPropertyValueString(item, _DisplayMember);
                        break;
                    }
                }

                return _Text;
            }

            public void ShowEdit(Cell cell)
            {
                if (m_HostedControl == null)
                    return;
                
            }

            private string GetPropertyValueString(object _Entity, string propertyName)
            {
                if (string.IsNullOrEmpty(propertyName))
                    return string.Empty;

                if (_Entity == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

                System.Reflection.PropertyInfo _PropertyInfo;
                _PropertyInfo = _Entity.GetType().GetProperty(propertyName);

                if (_PropertyInfo == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new Exception(propertyName + " property not found in entity."));

                object _Object;
                _Object = _PropertyInfo.GetValue(_Entity, null);

                if (_Object == null)
                    return string.Empty;

                return _Object.ToString();
            }

            private string GetValueString(DataRowView _Entity, string propertyName)
            {
                if (string.IsNullOrEmpty(propertyName))
                    return string.Empty;

                if (_Entity == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

                return _Entity[propertyName].ToString();
            }
        }
    }


    //private void PopulateData(ColumnHeaderCollection columns, NodeCollection nodes, Node nodeToCopy, PropertyDescriptorCollection properties, System.Windows.Forms.BindingSource data)
    //{ 
    //    //TODO: eliminate counter to 100

    //    int _Counter = 0;
    //    string _BindingColumnName;

    //    foreach (object _Entity in data)
    //    {

    //        Node _NewNode;
    //        _NewNode = nodeToCopy.DeepCopy();
    //        nodes.Add(_NewNode);


    //        _BindingColumnName = columns[0].ColumnName;

    //        //_NewNode.Text = m_ParentProperties[_BindingColumnName].GetValue(_Entity).ToString();

    //        _NewNode.Text = GetPropertyValueString(_Entity, _BindingColumnName, properties);

    //        Cell _Cell;
    //        for (int _ColumnCellIndex = 1; _ColumnCellIndex < _NewNode.Cells.Count; _ColumnCellIndex++)
    //        {
    //            _Cell = _NewNode.Cells[_ColumnCellIndex];
    //            _BindingColumnName = columns[_ColumnCellIndex].ColumnName;

    //            //_Cell.Text = GetPropertyValueString(_Entity, _BindingColumnName);
    //            _Cell.Text = GetPropertyValueString(_Entity, _BindingColumnName, properties);

    //            //HostedControl = CopyHostedControl(_Cell.HostedControl),
    //        }


    //        _Cell = _NewNode.Cells[0];
    //        if (!string.IsNullOrEmpty(_Cell.TagString))
    //        {
    //            string _ChildCollectionPropertyName;
    //            _ChildCollectionPropertyName = _Cell.TagString;

    //            if (_NewNode.HasColumns && _NewNode.HasChildNodes)
    //            {
    //                //Node _ChildNode;
    //                //_ChildNode = _NewNode.Nodes[0].DeepCopy();
    //                //_NewNode.Nodes.Clear();
                    
    //                //System.Windows.Forms.BindingSource _ChildrenDataSource;
    //                //_ChildrenDataSource = GetChildDataBindingSource(_Entity, _ChildCollectionPropertyName);

    //                //if (m_ChildProperties == null)
    //                //    m_ChildProperties = _ChildrenDataSource.CurrencyManager.GetItemProperties();

    //                //PopulateData(_NewNode.NodesColumns, _NewNode.Nodes, _ChildNode, m_ChildProperties, _ChildrenDataSource);
    //            }
    //        }


    //        _Counter++;
    //        if (_Counter >= 100)
    //            return;
    //    }
    //}
   


    //private void PopulateData(ColumnHeaderCollection columns, CellCollection cells, NodeCollection nodes, System.Windows.Forms.BindingSource data)
    //{
    //    //TODO: eliminate counter to 100


    //    int _Counter = 0;
    //    string _BindingColumnName;

    //    foreach (object _Entity in data)
    //    {
    //        _BindingColumnName = columns[0].ColumnName;
    //        Node _NewNode = new Node
    //        {
    //            Tag = _Entity,
    //            //TagString = m_FirstLevelNode.TagString,
    //            Text = GetPropertyValueString(_Entity, _BindingColumnName)
    //        };

    //        Cell _Cell;
    //        _Cell = cells[0];
    //        if (!string.IsNullOrEmpty(_Cell.TagString))
    //        {
    //            string _ChildCollectionPropertyName;
    //            _ChildCollectionPropertyName = _Cell.TagString;

    //            Node _Node;
    //            _Node = _Cell.Parent;

    //            if (_Node.HasColumns && _Node.HasChildNodes)
    //            {
    //                foreach (ColumnHeader _AddColumn in _Node.NodesColumns)
    //                {
    //                    _NewNode.NodesColumns.Add(_AddColumn.Copy());
    //                }

    //                Node _ChildNode;
    //                _ChildNode = _Node.Nodes[0].DeepCopy();
    //                _NewNode.Nodes.Clear();

    //                _NewNode.Nodes.Add(_ChildNode);

    //                //foreach (Node _AddNode in _Node.Nodes)
    //                //{
    //                //    _NewNode.Nodes.Add(_Node.DeepCopy());
    //                //}


    //                //ColumnHeaderCollection _ChildColumns;
    //                //_ChildColumns = _Node.NodesColumns;

               




    //                //NodeCollection _ChildNodes;
    //                //_ChildNodes = _Node.Nodes;

    //                //CellCollection _ChildCells;
    //                //_ChildCells = _ChildNodes[0].Cells;


    //                System.Windows.Forms.BindingSource _Binding;
    //                _Binding = GetChildDataBindingSource(_Entity, _ChildCollectionPropertyName);


    //                PopulateData(_NewNode.NodesColumns, _NewNode.Nodes[0].Cells, _NewNode.Nodes, _Binding);

                
    //            }
            
    //        }


    //        for (int _ColumnCellIndex = 1; _ColumnCellIndex < cells.Count; _ColumnCellIndex++)
    //        {
    //            _Cell = cells[_ColumnCellIndex];
    //            _BindingColumnName = columns[_ColumnCellIndex].ColumnName;

    //            _NewNode.Cells.Add(
    //                new Cell()
    //                {
    //                    HostedControl = CopyHostedControl(_Cell.HostedControl),
    //                    TagString = _Cell.TagString,
    //                    Text = GetPropertyValueString(_Entity, _BindingColumnName)
    //                });
    //        }

    //        nodes.Add(_NewNode);

    //        _Counter++;
    //        if (_Counter >= 100)
    //            return;
    //    }
    
    //}


    //private System.Windows.Forms.Control CopyHostedControl(System.Windows.Forms.Control controlToCopy)
    //{
    //    if (controlToCopy == null || typeof(DevComponents.DotNetBar.Controls.ComboBoxEx) != controlToCopy.GetType())
    //        return null;

    //    DevComponents.DotNetBar.Controls.ComboBoxEx _Combo;
    //    _Combo = controlToCopy as DevComponents.DotNetBar.Controls.ComboBoxEx;
        
    //    DevComponents.DotNetBar.Controls.ComboBoxEx _NewCombo;
    //    _NewCombo = new DevComponents.DotNetBar.Controls.ComboBoxEx()
    //    {
    //        DisplayMember = _Combo.DisplayMember,
    //        ValueMember = _Combo.ValueMember
    //        //    DataSource = _Combo.DataSource
    //    };


    //    foreach (object item in _Combo.Items)
    //    {
    //        _NewCombo.Items.Add(item);
    //    }
       

    //    return _NewCombo;
    //}


//private string GetPropertyValueString(object _Entity, string propertyName, PropertyDescriptorCollection properties)
//{
//    if (properties == null || string.IsNullOrEmpty(propertyName))
//        return string.Empty;

//    if (_Entity == null)
//        ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

//    object _Object;
//    _Object = properties[propertyName].GetValue(_Entity);

//    if (_Object == null)
//        return string.Empty;

//    return _Object.ToString();
//}

//private string GetPropertyValueString(object _Entity, string propertyName)
//{
//    if (string.IsNullOrEmpty(propertyName))
//        return string.Empty;

//    if (_Entity == null)
//        ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

//    System.Reflection.PropertyInfo _PropertyInfo;
//    _PropertyInfo = _Entity.GetType().GetProperty(propertyName);

//    if (_PropertyInfo == null)
//        ProjectCommon2.Helpers.ExceptionHelper.Throw(new Exception(propertyName + " property not found in entity."));

//    object _Object;
//    _Object = _PropertyInfo.GetValue(_Entity, null);

//    if (_Object == null)
//        return string.Empty;

//    return _Object.ToString();
//}



}
